package cn.tedu.csmall.order.webapi.service.impl;

import cn.tedu.csmall.cart.service.ICartService;
import cn.tedu.csmall.commons.exception.CoolSharkServiceException;
import cn.tedu.csmall.commons.pojo.order.dto.OrderAddDTO;
import cn.tedu.csmall.commons.pojo.order.entity.Order;
import cn.tedu.csmall.commons.pojo.stock.dto.StockReduceCountDTO;
import cn.tedu.csmall.commons.restful.JsonPage;
import cn.tedu.csmall.commons.restful.ResponseCode;
import cn.tedu.csmall.order.service.IOrderService;
import cn.tedu.csmall.order.webapi.mapper.OrderMapper;
import cn.tedu.csmall.stock.service.IStockService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

// order 模块是具备生产者特征的，他会被business模块调用，所以也要加@DubboService注解
@Slf4j
@Service
@DubboService
public class OrderServiceImpl implements IOrderService {

    @Autowired
    private OrderMapper orderMapper;

    // 添加@DubboReference 注解，表示当前业务逻辑层中要消费其他模块的服务了
    // 注解后声明应该是Dubbo 注册到Nacos 其他模块声明的业务逻辑层接口
    // 业务逻辑层接口的实现类会在Dubbo 框架下自动获取
    @DubboReference
    private IStockService stockService;
    @DubboReference
    private ICartService cartService;

    @Override
    public void orderAdd(OrderAddDTO orderAddDTO) {
        // 1.先减去订单中商品的库存数(调用Stock模块减少库存的方法)
        // 库存减少方法需要参数类型是StockReduceCountDTO ，我们需要先实例化它
        StockReduceCountDTO countDTO = new StockReduceCountDTO();
        countDTO.setCommodityCode(orderAddDTO.getCommodityCode());
        countDTO.setReduceCount(orderAddDTO.getCount());
        // 2.从购物车中删除用户选中的商品(调用Cart模块删除购物车中商品的方法)
        // 利用dubbo 调用cart 模块删除购物车中商品的方法 实现功能
        cartService.deleteUserCart(orderAddDTO.getUserId(),orderAddDTO.getCommodityCode());

        // 3.新增订单信息
        Order order = new Order();
        BeanUtils.copyProperties(orderAddDTO,order);

        orderMapper.insertOrder(order);
        log.info("新增订单信息为：{}",order);

        // 为了实现Seata 的回滚效果，在这里随机抛出异常
        if(Math.random() < 0.5){
            // 抛出异常
            String message = "发送随机异常";
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,message);
        }
    }
    // 分页查询所有订单的业务逻辑层方法
    // page 是页码，pageSize 是每页条数
    public JsonPage<Order> getAllOrdersByPage(Integer page, Integer pageSize){
        // PageHelper 框架实现分页的核心操作
        // 在要执行分页的查询运行之前，设置分页的条件
        // 设置的方式如下(固定的格式，PageHelper框架设计的)
        // pageHelper 设置page 为1就是查询第一页
        PageHelper.startPage(page,pageSize);
        // 下面开始持久层方法的调用
        // 此方法运行时因为设置了分页条件，sql语句中会自动出现limit关键字
        List<Order> list = orderMapper.findAllOrders();
        // 查询结果中list中包含的就是分页查询范围的数据了
        // 但是这个诗句不包括分页信息(总页数，总条数，是否是首页，是否是末页等)
        // 我们要利用PageHelper框架提供的PageInfo类型，来进行返回
        // PageInfo对象实例化时自动计算，并赋值到PageInfo对象中
        // 这些信息会在PageInfo对象实例化自动计算，并赋值到PageInfo对象中
        return JsonPage.restPage(new PageInfo<>(list));
    }

}
